package com.chenziwen.scala.chapter04

object Scala06_Function {
  def main(args: Array[String]): Unit = {
    // 函数的参数带默认值(类似以SpringMVC中的@RequestParam注解的效果)
    def f1(str: String): String = {
      str
    }

    def f2(str: String = "defaultValue"): String = {
      str
    }

    println(f1("param without default value"))
    println(f2())

    def sum1(num1: Int = 10, num2: Int): Int = {
      num1 + num2
    }

    def sum2(num1: Int, num2: Int = 10): Int = {
      num1 + num2
    }
    // 函数存在多个参数，每一个参数都可以设定默认值，那么这个时候，传递的参数到底是覆盖默认值，还是复制给没有默认值的参数，就不确定了（默认按照声明参数的顺序，从左到右）。在这种情况下：
    // 可以使用带名参数，如下所示，由于num1有默认值了，传参的时候我们只需要指定这个参数是num2即可
    println(sum1(num2 = 20))
    // sum2函数第二个参数num2有默认值，此时我们只传一个参数，那么这个参数会默认赋值给num1，编译不会报错
    println(sum2(30))
    // 两个参数同时赋值是，那么均会覆盖函数的默认值
    println(sum1(20, 20))
    println(sum2(30, 30))

    // 可变长参数，不确定参数的个数，类似于Java的 ...
    def f3(ids: Int*): Unit = {
      var sum = 0
      for (id <- ids) {
        sum += id
      }
      println("sum = " + sum)
    }

    f3(1, 2, 3)
    f3(1, 2, 3, 4)
    f3()

    // 递归函数:斐波那契数列
    // 递归函数在未执行之前是无法推断出来结果类型，在使用时必须有明确的返回值类型
    def f4(i: Int): Int = {
      if (i <= 0) {
        1
      } else {
        i * f4(i - 1)
      }
    }

    println(f4(5))

    // 过程函数：将函数的返回类型为Unit的函数称之为过程（既没有返回值类型，也没有等号）。如果明确函数没有返回值，那么等号也可以省略
    def f5(str: String) {
      println(str)
    }

    f5("content")

    // 惰性函数：当函数返回值被声明为lazy时，函数的执行将会被推迟，直到我们首次对此取值。在Java的某些框架中被称之为懒加载
    def f6(): Unit = {
      println("函数f6被执行")
    }

    val result = f6()
    println("............")
    println(result)
    println("---------------------------------")
    lazy val lazyResult = f6()
    println("............")
    println(lazyResult)


  }
}
